import type { Component } from 'vue'

interface LoaderOptions {
  recursive?: boolean
  pattern?: string
  nameFormatter?: (name: string) => string
}

interface LoadedComponent {
  name: string
  component: Component
  metadata?: Record<string, any>
}

class DynamicLoader {
  private static instance: DynamicLoader
  private cache: Map<string, LoadedComponent[]> = new Map()

  private constructor() {}

  static getInstance(): DynamicLoader {
    if (!DynamicLoader.instance) {
      DynamicLoader.instance = new DynamicLoader()
    }
    return DynamicLoader.instance
  }

  async loadComponents(
    path: string,
    options: LoaderOptions = {}
  ): Promise<LoadedComponent[]> {
    const {
      recursive = true,
      pattern = 'index.vue',
      nameFormatter = (name: string) => name
    } = options

    const cacheKey = `${path}-${recursive}-${pattern}`
    if (this.cache.has(cacheKey)) {
      return this.cache.get(cacheKey)!
    }

    const modules = import.meta.glob<{ default: Component & { metadata?: Record<string, any> } }>(
      '/src/views/**/*.vue',
      { eager: true }
    )

    const components: LoadedComponent[] = []
    const basePath = `/src/views/${path}`

    for (const modulePath in modules) {
      if (!modulePath.startsWith(basePath)) {
        continue
      }

      if (!recursive && modulePath.split('/').length > basePath.split('/').length + 2) {
        continue
      }

      if (!modulePath.endsWith(pattern)) {
        continue
      }

      try {
        const module = modules[modulePath]
        const component = module.default

        if (!component) {
          console.warn(`No default export found in ${modulePath}`)
          continue
        }

        const name = this.extractComponentName(modulePath)
        const metadata = component.metadata || this.extractMetadataFromPath(modulePath)
        
        components.push({
          name,
          component,
          metadata
        })
      } catch (error) {
        console.error(`Failed to load component from ${modulePath}:`, error)
      }
    }

    this.cache.set(cacheKey, components)
    return components
  }

  private extractComponentName(modulePath: string): string {
    const matches = modulePath.match(/\/([^/]+)\/[^/]+$/)
    return matches ? matches[1] : 'unknown'
  }

  private extractMetadataFromPath(modulePath: string): Record<string, any> {
    const pathParts = modulePath.split('/')
    const componentType = pathParts[pathParts.length - 2]
    const category = pathParts[pathParts.length - 3] || 'other'

    return {
      type: componentType,
      category,
      label: this.formatComponentName(componentType),
      props: {
        base: {},
        style: {}
      }
    }
  }

  private formatComponentName(name: string): string {
    return name
      .split(/[-_]/)
      .map(word => word.charAt(0).toUpperCase() + word.slice(1))
      .join(' ')
  }

  clearCache(path?: string) {
    if (path) {
      for (const key of this.cache.keys()) {
        if (key.startsWith(path)) {
          this.cache.delete(key)
        }
      }
    } else {
      this.cache.clear()
    }
  }
}

export const dynamicLoader = DynamicLoader.getInstance() 